/**
 *Copyright (c) 2024 watereyes
 * safetymanagement is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan
 * PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */
package com.koron.scene.service.impl;


import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import com.koron.audit.approval.AfterApprovalService;
import com.koron.audit.domain.Audit;
import com.koron.audit.management.FlowManagement;
import com.koron.common.bean.StaffBean;
import com.koron.common.domain.DataBean;
import com.koron.common.generator.DefaultIdGenerator;
import com.koron.scene.domain.ActivityStage;
import com.koron.scene.domain.SiteActivity;
import com.koron.scene.domain.StageItem;
import com.koron.scene.mapper.*;
import com.koron.scene.service.api.SiteActivityService;
import com.koron.scene.utils.BusinessCode;
import com.koron.system.domain.DictData;
import com.koron.system.service.api.DictDataService;
import org.apache.commons.lang3.StringUtils;
import org.koron.ebs.mybatis.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.swan.bean.MessageBean;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class SiteActivityServiceImpl implements SiteActivityService, AfterApprovalService, InitializingBean {

    private final static  Logger logger = LoggerFactory.getLogger(SiteActivityServiceImpl.class);

    @Autowired
    private DictDataService dataService;

    // 状态:1草稿2会签中3已会签
    private Integer STATUS_1 = 1;
    private Integer STATUS_2 = 2;
    private Integer STATUS_3 = 3;

    @Value("${site_activity_key}")
    private String templateKey;

    @Autowired
    private FlowManagement flowManagement;

    @Override
    public DataBean<SiteActivity> fetchActivity(String corpCode, String name, String organizerName, Integer status, Integer start, Integer rows) {
        if (logger.isDebugEnabled()) {
            logger.debug("corpCode = {}, name = {}, organizerName = {}", corpCode, name, organizerName);
        }
        try (SessionFactory factory = new SessionFactory()) {
            SiteActivityMapper mapper = factory.getMapper(SiteActivityMapper.class);
            List<SiteActivity> activities = mapper.queryByCondition(corpCode, name, organizerName, status, start, rows);
            Integer total = mapper.countByCondition(corpCode, name, organizerName, status);
            DataBean<SiteActivity> dataBean = new DataBean<>();
            dataBean.setList(activities);
            dataBean.setPageSize(rows);
            dataBean.setTotalNumber(total);
            dataBean.setTotalPage(total > rows ? (total % rows == 0 ? total / rows : total / rows + 1) : 1);
            dataBean.setPageNo(start / rows + 1);
            return dataBean;
        }
    }


    @Override
    public SiteActivity fetchOne(String id) {
        if (logger.isDebugEnabled()) {
            logger.debug("id = {}", id);
        }
        try (SessionFactory factory = new SessionFactory()) {
            SiteActivity siteActivity = factory.getMapper(SiteActivityMapper.class).queryOne(id);
            if (siteActivity != null) {
                siteActivity.setStages(factory.getMapper(ActivityStageMapper.class).queryStages(id));
                List<ActivityStage> stages = siteActivity.getStages();
                if (stages != null && !stages.isEmpty()) {
                    for (ActivityStage fs : stages) {
                        setName(fs);
                        fs.setItemList(factory.getMapper(StageItemMapper.class).queryForStage(fs.getId()));
                    }
                }
            }
            return siteActivity;
        }
    }

    private void setName(ActivityStage stage) {
        Map<String, DictData> cacheMap = dataService.getCacheMap();
        if (StringUtils.isNotBlank(stage.getJsaTypeId())) {
            DictData dictData = cacheMap.get(stage.getJsaTypeId());
            stage.setJsaTypeName(dictData != null? dictData.getDictLabel() : "");
        }
    }

    @Override
    public MessageBean batchDetele(List<String> idList) {
        SessionFactory factory = null;
        MessageBean msg = MessageBean.create(BusinessCode.SUCCESS.getCode(), BusinessCode.SUCCESS.getDescription(), void.class);
        if (idList == null || idList.isEmpty()) {
            msg.setCode(BusinessCode.INSUFFICIENT_PARAM.getCode());
            msg.setDescription(BusinessCode.INSUFFICIENT_PARAM.getDescription());
            return msg;
        }
        try {
            factory = new SessionFactory();
            SiteActivityMapper mapper = factory.getMapper(SiteActivityMapper.class);
            // 根据 id list 查询作业活动
            List<SiteActivity> siteActivities = mapper.queryForListByIds(idList);
            if (!siteActivities.isEmpty()) {
                for (SiteActivity siteActivity : siteActivities) {
                    if (STATUS_1 != siteActivity.getStatus()){
                        factory.close(false);
                        msg.setCode(BusinessCode.SITEACTIVITY_STATUS_DELETE.getCode());
                        msg.setDescription(BusinessCode.SITEACTIVITY_STATUS_DELETE.getDescription());
                        return msg;
                    }
                }
                mapper.batchDetele(idList);
            }
            factory.close(true);
            return msg;
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            if (factory != null) {
                factory.close(false);
            }
            logger.error(e.getMessage(),e);
        }
        return msg;
    }


    @Override
    public Integer persist(SiteActivity activity, StaffBean user) {
        SessionFactory factory = null;
        try {
            Integer start = null, rows = null, status = null;
            String organizerName = null;
            SiteActivity dest = null;
            factory = new SessionFactory();
            SiteActivityMapper mapper = factory.getMapper(SiteActivityMapper.class);
            List<SiteActivity> activities = mapper.queryByCondition(activity.getCorpCode(), activity.getName(), organizerName, status, start, rows);
            if (activities != null && !activities.isEmpty()) {
                activities = activities.stream().filter(one -> one.getName().equals(activity.getName())).collect(Collectors.toList());
                dest = !activities.isEmpty() ? activities.get(0) : null;
            }

            if (StringUtils.isBlank(activity.getId())) {
                if (dest != null) {
                    factory.close(false);
                    return BusinessCode.SITEACTIVITY_NAME_DUP.getCode();
                }
                activity.setId(DefaultIdGenerator.getInstance().generateLongId());
                // 新增保存时，只要status(草稿2会签中3已会签) 不是会签中，都为草稿 1
                if (STATUS_2 != activity.getStatus()) {
                    activity.setStatus(STATUS_1);
                }
                if (mapper.insert(activity) > 0) {
                    List<StageItem> itemAll = new ArrayList<>();
                    List<ActivityStage> stages = activity.getStages();
                    if (stages != null && !stages.isEmpty()) {
                        for (ActivityStage stage : stages) {
                            stage.setId(DefaultIdGenerator.getInstance().generateLongId());
                            stage.setSiteActivityId(activity.getId());
                            List<StageItem> itemList = stage.getItemList();
                            if (itemList != null && !itemList.isEmpty()) {
                                for (StageItem stageItem : itemList) {
                                    stageItem.setId(DefaultIdGenerator.getInstance().generateLongId());
                                    stageItem.setActivityStageId(stage.getId());
                                }
                            }
                            itemAll.addAll(itemList);
                        }
                        if (factory.getMapper(ActivityStageMapper.class).batchInsert(stages) > 0) {
                            if (!itemAll.isEmpty()) {
                                factory.getMapper(StageItemMapper.class).batchInsert(itemAll);
                            }
                        }
                    }
                    if (STATUS_2 == activity.getStatus()){// 如果是状态是 会签中，则进入审批流程
                        Audit audit = new Audit("作业活动", "作业活动审批", user.getName(), new Date());
                        audit.setTitle("作业活动");
                        audit.setDescription("作业活动审批");
                        audit.setCorpCode(activity.getCorpCode());
                        audit.setCorpCode(activity.getName());

                        audit.setId(DefaultIdGenerator.getInstance().generateLongId());
                        audit.setInitiatorCode(user.getCode());
                        audit.setTarget(this.getClass().getName());
                        audit.setTemplateKey(templateKey);
                        audit.setOperation(1);
                        audit.setState(1);
                        audit.setFlowType(1);
                        audit.setFlowName("新增作业活动");
                        List<String> idList = Arrays.asList(activity.getId());
                        audit.setBusinessIds(new Gson().toJson(idList));
                        Map<String, Object> businessMap = new HashMap<>();
                        businessMap.put("manager", activity.getOrganizerCode());
                        businessMap.put("executors", "1-" + activity.getParticipatorCodes());
                        if (!flowManagement.initFlow(user, audit, businessMap)) {
                            factory.close(false);
                            return BusinessCode.MESSAGE_CODE_FLOW_EXCEPTION.getCode();
                        }
                    }
                    factory.close(true);
                    return BusinessCode.SUCCESS.getCode();
                }
            } else {
                if (dest != null && !dest.getId().equals(activity.getId())) {
                    factory.close(false);
                    return BusinessCode.JSATEMPLATE_NAME_DUP.getCode();
                }
                // 根据id查询 现场作业活动表
                SiteActivity siteActivity = mapper.queryOne(activity.getId());
                if (siteActivity == null) {
                    factory.close(false);
                    return BusinessCode.SITEACTIVITY_QUERY.getCode();
                } else if (siteActivity.getStatus() != STATUS_1) {
                    factory.close(false);
                    return BusinessCode.SITEACTIVITY_STATUS_UPDATE.getCode();
                }
                // 保存时，只要status(草稿2会签中3已会签) 不是会签中，都为草稿 1
                if (STATUS_2 != activity.getStatus()) {
                    activity.setStatus(STATUS_1);
                }
                if (mapper.update(activity) > 0) {
                    List<StageItem> items = new ArrayList<>();
                    List<StageItem> formerItems = new ArrayList<>();
                    List<ActivityStage> stages = activity.getStages();
                    List<ActivityStage> formerStages = factory.getMapper(ActivityStageMapper.class).queryStages(activity.getId());
                    if (formerStages != null && !formerStages.isEmpty()) {
                        for (ActivityStage fs : formerStages) {
                            formerItems.addAll(factory.getMapper(StageItemMapper.class).queryForStage(fs.getId()));
                        }
                    }

                    if (stages != null && !stages.isEmpty()) {
                        stages.stream().forEach(s -> s.setSiteActivityId(activity.getId()));
                        List<ActivityStage> istages = stages.stream().filter(s -> StringUtils.isBlank(s.getId())).collect(Collectors.toList());
                        List<ActivityStage> ustages = stages.stream().filter(s -> StringUtils.isNotBlank(s.getId())).collect(Collectors.toList());
                        formerStages.removeAll(stages);
                        if (!ustages.isEmpty()) {
                            factory.getMapper(ActivityStageMapper.class).batchUpdate(ustages);
                            ustages.forEach(s -> items.addAll(s.getItemList()));
                        }
                        if (!istages.isEmpty()) {
                            for (ActivityStage one : istages) {
                                one.setId(DefaultIdGenerator.getInstance().generateLongId());
                                List<StageItem> citems = one.getItemList();
                                if (citems != null && !citems.isEmpty()) {
                                    for (StageItem citem : citems) {
                                        citem.setActivityStageId(one.getId());
                                    }
                                    items.addAll(citems);
                                }
                            }
                            factory.getMapper(ActivityStageMapper.class).batchInsert(istages);
                        }
                        if (!formerStages.isEmpty()) {
                            factory.getMapper(ActivityStageMapper.class).batchDetele(formerStages.stream().map(ActivityStage::getId).collect(Collectors.toList()));
                        }
                    }

                    if (items != null && !items.isEmpty()) {
                        List<StageItem> iitems = items.stream().filter(one -> StringUtils.isBlank(one.getId())).collect(Collectors.toList());
                        List<StageItem> uitems = items.stream().filter(one -> StringUtils.isNotBlank(one.getId())).collect(Collectors.toList());
                        formerItems.removeAll(items);
                        if (!uitems.isEmpty()) {
                            factory.getMapper(StageItemMapper.class).batchUpdate(uitems);
                        }
                        if (!iitems.isEmpty()) {
                            for (StageItem si : iitems) {
                                si.setId(DefaultIdGenerator.getInstance().generateLongId());
                            }
                            factory.getMapper(StageItemMapper.class).batchInsert(iitems);
                        }
                        if (!formerItems.isEmpty()) {
                            factory.getMapper(StageItemMapper.class).batchDetele(formerItems.stream().map(StageItem::getId).collect(Collectors.toList()));
                        }
                    }
                    if (STATUS_2 == activity.getStatus()){// 如果是状态是 会签中，则进入审批流程
                        Audit audit = new Audit("作业活动", "作业活动审批", user.getName(), new Date());
                        audit.setTitle("作业活动");
                        audit.setDescription("作业活动审批");
                        audit.setCorpCode(activity.getCorpCode());
                        audit.setCorpCode(activity.getName());

                        audit.setId(DefaultIdGenerator.getInstance().generateLongId());
                        audit.setInitiatorCode(user.getCode());
                        audit.setTarget(this.getClass().getName());
                        audit.setTemplateKey(templateKey);
                        audit.setOperation(1);
                        audit.setState(1);
                        audit.setFlowType(1);
                        audit.setFlowName("新增作业活动");
                        List<String> idList = Arrays.asList(activity.getId());
                        audit.setBusinessIds(new Gson().toJson(idList));
                        Map<String, Object> businessMap = new HashMap<>();
                        businessMap.put("manager", activity.getOrganizerCode());
                        businessMap.put("executors", "1-" + activity.getParticipatorCodes());
                        if (!flowManagement.initFlow(user, audit, businessMap)) {
                            factory.close(false);
                            return BusinessCode.MESSAGE_CODE_FLOW_EXCEPTION.getCode();
                        }
                    }
                    factory.close(true);
                    return BusinessCode.SUCCESS.getCode();
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            logger.error(e.getMessage(),e);
        }
        if (factory != null) {
            factory.close(false);
        }
        return BusinessCode.EXCEPTION.getCode();
    }


    @Override
    public Integer saveStage(ActivityStage stage) {
        SessionFactory factory = null;
        try {
            ActivityStage dest = null;
            factory = new SessionFactory();
            ActivityStageMapper mapper = factory.getMapper(ActivityStageMapper.class);
            List<ActivityStage> stages = mapper.queryForName(stage.getSiteActivityId(), stage.getName());
            if (stages != null && !stages.isEmpty()) {
                stages = stages.stream().filter(one -> one.getName().equals(stage.getName())).collect(Collectors.toList());
                dest = !stages.isEmpty() ? stages.get(0) : null;
            }

            if (StringUtils.isBlank(stage.getId())) {
                if (dest != null) {
                    factory.close(false);
                    return BusinessCode.ACTIVITYSTAGE_NAME_DUP.getCode();
                }
                stage.setId(DefaultIdGenerator.getInstance().generateLongId());
                if (mapper.insert(stage) > 0 && persistItems(factory, stage.getItemList(), stage.getId())) {
                    factory.close(true);
                    return BusinessCode.SUCCESS.getCode();
                }
            } else {
                if (dest != null && !dest.getId().equals(stage.getId())) {
                    factory.close(false);
                    return BusinessCode.ACTIVITYSTAGE_NAME_DUP.getCode();
                }
                if (mapper.update(stage) > 0 && persistItems(factory, stage.getItemList(), stage.getId())) {
                    factory.close(true);
                    return BusinessCode.SUCCESS.getCode();
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
        }
        if (factory != null) {
            factory.close(false);
        }
        return BusinessCode.EXCEPTION.getCode();
    }


    private boolean persistItems(SessionFactory factory, List<StageItem> items, String activityStageId) {
        try {
            if (items == null || items.isEmpty()) {
                return true;
            }
            items.stream().forEach(s -> s.setActivityStageId(activityStageId));
            StageItemMapper mapper = factory.getMapper(StageItemMapper.class);
            List<StageItem> ulist = items.stream().filter(item -> StringUtils.isNotBlank(item.getId())).collect(Collectors.toList());
            List<StageItem> ilist = items.stream().filter(item -> StringUtils.isBlank(item.getId())).collect(Collectors.toList());
            List<StageItem> formers = mapper.queryForStage(activityStageId);
            formers.removeAll(ulist);
            if (!ulist.isEmpty()) {
                mapper.batchUpdate(ulist);
            }
            if (!ilist.isEmpty()) {
                for (StageItem stageItem : ilist) {
                    stageItem.setId(DefaultIdGenerator.getInstance().generateLongId());
                }
                mapper.batchInsert(ilist);
            }
            if (!formers.isEmpty()) {
                mapper.batchDetele(formers.stream().map(StageItem::getId).collect(Collectors.toList()));
            }
            return true;
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            return false;
        }
    }


    @Override
    public ActivityStage detailStage(String activityStageId) {
        if (logger.isDebugEnabled()) {
            logger.debug("activityStageId = {}", activityStageId);
        }
        try (SessionFactory factory = new SessionFactory()) {
            ActivityStage stage = factory.getMapper(ActivityStageMapper.class).queryOne(activityStageId);
            if (stage != null) {
                stage.setItemList(factory.getMapper(StageItemMapper.class).queryForStage(stage.getId()));
            }
            return stage;
        }
    }

    @Override
    public void editApproval(Audit audit) {
        Optional.ofNullable(audit)
                .map(obj -> obj.getBusinessIds())
                .map(ids -> {
                    List<String> list = JSON.parseArray(ids, String.class);
                    return Optional.ofNullable(list);
                }).map(idsList -> {
            List<String> idList = idsList.get();
            Optional.ofNullable(idList).map(ids -> {
                SessionFactory factory = new SessionFactory();
                try {
                    SiteActivityMapper mapper = factory.getMapper(SiteActivityMapper.class);
                    for (String id : ids) {
                        if (mapper.updateSiteActivityToStatusById(id, STATUS_3) != 1) {
                            factory.close(false);
                            return null;
                        }
                    }
                    factory.close();
                } catch (Exception e) {
                    logger.error(e.getMessage(),e);
                    factory.close(false);
                }
                return null;
            });
            return null;
        });
    }

    @Override
    public void discardApproval(Audit audit) {

    }

    @Override
    public void processDiscard(Audit audit) {
        List<String> list = JSON.parseArray(audit.getBusinessIds(), String.class);
        if (list != null && !list.isEmpty()) {
            String id = list.get(0);
            try (SessionFactory factory = new SessionFactory();) {
                factory.getMapper(SiteActivityMapper.class).updateSiteActivityToStatusById(id, STATUS_1);
            }
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        flowManagement.getHandlers().put(this.getClass().getName(), new SiteActivityServiceImpl());
    }

    @Override
    public void reject(Audit audit, List<String> userIdList) {
        // TODO 流程驳回操作
    }

    @Override
    public void passApproval(Integer operation, Audit audit) {
        // TODO 流程提交成功操作
    }
}
